bitkeeper revision 1.1159.187.22 (41a89729VHxMK8Tp4qcLrOPCoZrdog)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sat, 27 Nov 2004 15:03:05 +0000 (15:03 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sat, 27 Nov 2004 15:03:05 +0000 (15:03 +0000)
First cut for VM86 support, based on Stephan Diestelhorst's patches. It
doesn't actually work yet -- it's possible that e.g., signal delivery is
broken.

linux-2.6.9-xen-sparse/arch/xen/i386/kernel/entry.S
xen/arch/x86/pdb-stub.c
xen/arch/x86/traps.c
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_32/seg_fixup.c
xen/include/asm-x86/debugger.h
xen/include/asm-x86/x86_32/asm_defns.h
xen/include/asm-x86/x86_32/regs.h
xen/include/public/xen.h

index 1d19d7986433da709e72fff7a400c65be19117b7..a3189508d51a5a2f008e2b71733e4956f7291694 100644 (file)
@@ -309,6 +309,8 @@ syscall_exit:
        testw $_TIF_ALLWORK_MASK, %cx   # current->work
        jne syscall_exit_work
 restore_all:
+       testl $VM_MASK, EFLAGS(%esp)
+       jnz resume_vm86
        movb EVENT_MASK(%esp), %al
        notb %al                        # %al == ~saved_mask
        andb evtchn_upcall_mask(%esi),%al
@@ -316,6 +318,13 @@ restore_all:
        jnz restore_all_enable_events   #     != 0 => reenable event delivery
        RESTORE_ALL
 
+resume_vm86:
+       RESTORE_REGS
+       pushl %eax,(%esp)
+       movl $__HYPERVISOR_switch_vm86,%eax
+       int $0x82                       # Atomically enables events delivery
+       ud2
+
        # perform work that needs to be done immediately before resumption
        ALIGN
 work_pending:
@@ -546,7 +555,8 @@ ENTRY(failsafe_callback)
 2:      popl %es
 3:      popl %fs
 4:      popl %gs
-5:     iret
+        SAVE_ALL
+        jmp  ret_from_exception
 .section .fixup,"ax";  \
 6:     movl $0,(%esp); \
        jmp 1b;         \
@@ -556,12 +566,6 @@ ENTRY(failsafe_callback)
        jmp 3b;         \
 9:     movl $0,(%esp); \
        jmp 4b;         \
-10:    pushl %ss;      \
-       popl %ds;       \
-       pushl %ss;      \
-       popl %es;       \
-       pushl $11;      \
-       call do_exit;   \
 .previous;             \
 .section __ex_table,"a";\
        .align 4;       \
@@ -569,7 +573,6 @@ ENTRY(failsafe_callback)
        .long 2b,7b;    \
        .long 3b,8b;    \
        .long 4b,9b;    \
-       .long 5b,10b;   \
 .previous
 
 ENTRY(coprocessor_error)
@@ -887,7 +890,7 @@ ENTRY(sys_call_table)
        .long sys_iopl          /* 110 */
        .long sys_vhangup
        .long sys_ni_syscall    /* old "idle" system call */
-       .long sys_ni_syscall    /* disable sys_vm86old */
+       .long sys_vm86old
        .long sys_wait4
        .long sys_swapoff       /* 115 */
        .long sys_sysinfo
index e301bf387a5ee65de37bb858e1a5269610013824..88aa373122789b55bafda67f8c0594c393756712 100644 (file)
@@ -1083,13 +1083,17 @@ int pdb_handle_exception(int exceptionVector,
     int watchdog_save;
     unsigned long cr3 = read_cr3();
 
+    /* No vm86 handling here as yet. */
+    if ( VM86_MODE(xen_regs) )
+        return 1;
+
     /* If the exception is an int3 from user space then pdb is only
        interested if it re-wrote an instruction set the breakpoint.
        This occurs when leaving a system call from a domain.
     */
-    if ( exceptionVector == 3 &&
-        (xen_regs->cs & 3) == 3 && 
-        xen_regs->eip != pdb_system_call_next_addr + 1)
+    if ( (exceptionVector == 3) &&
+        RING_3(xen_regs) && 
+        (xen_regs->eip != (pdb_system_call_next_addr + 1)) )
     {
         TRC(printf("pdb: user bkpt (0x%x) at 0x%x:0x%lx:0x%x\n", 
                   exceptionVector, xen_regs->cs & 3, cr3, xen_regs->eip));
index f07740220b4c95be1ae5a7ceafc87e4f8c2915a6..842de24582d532e57cef05fd9c621af168b1f1f7 100644 (file)
@@ -54,6 +54,8 @@
 
 #if defined(__i386__)
 
+#define GUEST_FAULT(_r) (likely(VM86_MODE(_r) || !RING_0(_r)))
+
 #define DOUBLEFAULT_STACK_SIZE 1024
 static struct tss_struct doublefault_tss;
 static unsigned char doublefault_stack[DOUBLEFAULT_STACK_SIZE];
@@ -164,7 +166,7 @@ void show_registers(struct xen_regs *regs)
     unsigned long esp;
     unsigned short ss, ds, es, fs, gs;
 
-    if ( regs->cs & 3 )
+    if ( GUEST_FAULT(regs) )
     {
         esp = regs->esp;
         ss  = regs->ss & 0xffff;
@@ -247,7 +249,7 @@ static inline int do_trap(int trapnr, char *str,
 
     DEBUGGER_trap_entry(trapnr, regs);
 
-    if ( !(regs->cs & 3) )
+    if ( !GUEST_FAULT(regs) )
         goto xen_fault;
 
     ti = current->thread.traps + trapnr;
@@ -313,7 +315,7 @@ asmlinkage int do_int3(struct xen_regs *regs)
 
     DEBUGGER_trap_entry(TRAP_int3, regs);
 
-    if ( unlikely((regs->cs & 3) == 0) )
+    if ( !GUEST_FAULT(regs) )
     {
         DEBUGGER_trap_fatal(TRAP_int3, regs);
         show_registers(regs);
@@ -419,7 +421,7 @@ asmlinkage int do_page_fault(struct xen_regs *regs)
             return EXCRET_fault_fixed; /* successfully copied the mapping */
     }
 
-    if ( unlikely(!(regs->cs & 3)) )
+    if ( !GUEST_FAULT(regs) )
         goto xen_fault;
 
     ti = d->thread.traps + 14;
@@ -479,8 +481,10 @@ asmlinkage int do_general_protection(struct xen_regs *regs)
 
     DEBUGGER_trap_entry(TRAP_gp_fault, regs);
     
-    /* Badness if error in ring 0, or result of an interrupt. */
-    if ( !(regs->cs & 3) || (regs->error_code & 1) )
+    if ( regs->error_code & 1 )
+        goto hardware_gp;
+
+    if ( !GUEST_FAULT(regs) )
         goto gp_in_kernel;
 
     /*
@@ -507,7 +511,7 @@ asmlinkage int do_general_protection(struct xen_regs *regs)
     {
         /* This fault must be due to <INT n> instruction. */
         ti = current->thread.traps + (regs->error_code>>3);
-        if ( TI_GET_DPL(ti) >= (regs->cs & 3) )
+        if ( TI_GET_DPL(ti) >= (VM86_MODE(regs) ? 3 : (regs->cs & 3)) )
         {
             tb->flags = TBF_EXCEPTION;
             regs->eip += 2;
@@ -545,6 +549,7 @@ asmlinkage int do_general_protection(struct xen_regs *regs)
 
     DEBUGGER_trap_fatal(TRAP_gp_fault, regs);
 
+ hardware_gp:
     show_registers(regs);
     panic("CPU%d GENERAL PROTECTION FAULT\n[error_code=%04x]\n",
           smp_processor_id(), regs->error_code);
@@ -641,7 +646,7 @@ asmlinkage int do_debug(struct xen_regs *regs)
         goto out;
     }
 
-    if ( (regs->cs & 3) == 0 )
+    if ( !GUEST_FAULT(regs) )
     {
         /* Clear TF just for absolute sanity. */
         regs->eflags &= ~EF_TF;
index 32915e4a05d029a85c5df652b44f3b547282b4a8..4bfcb945d34203bbc500bd15313381a87eb03694 100644 (file)
@@ -73,10 +73,13 @@ ENTRY(continue_nonidle_task)
 restore_all_guest:
         testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
         jnz  failsafe_callback
+        testl $X86_EFLAGS_VM,XREGS_eflags(%esp)
+        jnz  restore_all_vm86
 FLT1:   movl XREGS_ds(%esp),%ds
 FLT2:   movl XREGS_es(%esp),%es
 FLT3:   movl XREGS_fs(%esp),%fs
 FLT4:   movl XREGS_gs(%esp),%gs
+restore_all_vm86:
         popl %ebx
         popl %ecx
         popl %edx
@@ -218,10 +221,11 @@ process_softirqs:
 /*   {EIP, CS, EFLAGS, [ESP, SS]}                                        */
 /* %edx == trap_bounce, %ebx == task_struct                              */
 /* %eax,%ecx are clobbered. %gs:%esi contain new XREGS_ss/XREGS_esp. */
-create_bounce_frame:        
+create_bounce_frame:
+        movl XREGS_eflags+4(%esp),%ecx
         movb XREGS_cs+4(%esp),%cl
-        testb $2,%cl
-        jz   1f /* jump if returning to an existing ring-1 activation */
+        testl $(2|X86_EFLAGS_VM),%ecx
+        jz   ring1 /* jump if returning to an existing ring-1 activation */
         /* obtain ss/esp from TSS -- no current ring-1 activations */
         movl DOMAIN_processor(%ebx),%eax
         /* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */
@@ -232,48 +236,73 @@ create_bounce_frame:
         addl $init_tss + 12,%eax
         movl (%eax),%esi /* tss->esp1 */
 FLT7:   movl 4(%eax),%gs /* tss->ss1  */
-        /* base of stack frame must contain ss/esp (inter-priv iret) */
-        subl $8,%esi
+        testl $X86_EFLAGS_VM,XREGS_eflags+4(%esp)
+        jz   nvm86_1
+       subl $16,%esi       /* push ES/DS/FS/GS (VM86 stack frame) */
+       movl XREGS_es+4(%esp),%eax
+FLT8:   movl %eax,%gs:(%esi)
+       movl XREGS_ds+4(%esp),%eax
+FLT9:   movl %eax,%gs:4(%esi)
+       movl XREGS_fs+4(%esp),%eax
+FLT10:  movl %eax,%gs:8(%esi)
+       movl XREGS_gs+4(%esp),%eax
+FLT11:  movl %eax,%gs:12(%esi)
+nvm86_1:subl $8,%esi        /* push SS/ESP (inter-priv iret) */
         movl XREGS_esp+4(%esp),%eax
-FLT8:   movl %eax,%gs:(%esi) 
+FLT12:  movl %eax,%gs:(%esi) 
         movl XREGS_ss+4(%esp),%eax
-FLT9:   movl %eax,%gs:4(%esi) 
-        jmp 2f
-1:      /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
+FLT13:  movl %eax,%gs:4(%esi) 
+        jmp 1f
+ring1:  /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
         movl XREGS_esp+4(%esp),%esi
-FLT10:  movl XREGS_ss+4(%esp),%gs 
-2:      /* Construct a stack frame: EFLAGS, CS/EIP */
+FLT14:  movl XREGS_ss+4(%esp),%gs 
+1:      /* Construct a stack frame: EFLAGS, CS/EIP */
         subl $12,%esi
         movl XREGS_eip+4(%esp),%eax
-FLT11:  movl %eax,%gs:(%esi) 
+FLT15:  movl %eax,%gs:(%esi) 
         movl XREGS_cs+4(%esp),%eax
-FLT12:  movl %eax,%gs:4(%esi) 
+FLT16:  movl %eax,%gs:4(%esi) 
         movl XREGS_eflags+4(%esp),%eax
-FLT13:  movl %eax,%gs:8(%esi)
+FLT17:  movl %eax,%gs:8(%esi)
         movb TRAPBOUNCE_flags(%edx),%cl
         test $TBF_EXCEPTION_ERRCODE,%cl
         jz   1f
         subl $4,%esi                    # push error_code onto guest frame
         movl TRAPBOUNCE_error_code(%edx),%eax
-FLT14:  movl %eax,%gs:(%esi)
+FLT18:  movl %eax,%gs:(%esi)
         testb $TBF_EXCEPTION_CR2,%cl
         jz   2f
         subl $4,%esi                    # push %cr2 onto guest frame
         movl TRAPBOUNCE_cr2(%edx),%eax
-FLT15:  movl %eax,%gs:(%esi)
+FLT19:  movl %eax,%gs:(%esi)
 1:      testb $TBF_FAILSAFE,%cl
         jz   2f
         subl $16,%esi                # add DS/ES/FS/GS to failsafe stack frame
-        movl XREGS_ds+4(%esp),%eax
-FLT16:  movl %eax,%gs:(%esi) 
+        testl $X86_EFLAGS_VM,XREGS_eflags+4(%esp)
+        jz   nvm86_2
+        xorl %eax,%eax               # VM86: we write zero selector values
+FLT20:  movl %eax,%gs:(%esi) 
+FLT21:  movl %eax,%gs:4(%esi)
+FLT22:  movl %eax,%gs:8(%esi) 
+FLT23:  movl %eax,%gs:12(%esi)
+        jmp  2f
+nvm86_2:movl XREGS_ds+4(%esp),%eax   # non-VM86: write real selector values
+FLT24:  movl %eax,%gs:(%esi) 
         movl XREGS_es+4(%esp),%eax
-FLT17:  movl %eax,%gs:4(%esi)
+FLT25:  movl %eax,%gs:4(%esi)
         movl XREGS_fs+4(%esp),%eax
-FLT18:  movl %eax,%gs:8(%esi) 
+FLT26:  movl %eax,%gs:8(%esi) 
         movl XREGS_gs+4(%esp),%eax
-FLT19:  movl %eax,%gs:12(%esi)
+FLT27:  movl %eax,%gs:12(%esi)
 2:      movb $0,TRAPBOUNCE_flags(%edx)
-        /* Rewrite our stack frame and return to ring 1. */
+        testl $X86_EFLAGS_VM,XREGS_eflags+4(%esp)
+        jz   nvm86_3
+        xorl %eax,%eax      /* zero DS-GS, just as a real CPU would */
+        movl %eax,XREGS_ds+4(%esp)
+        movl %eax,XREGS_es+4(%esp)
+        movl %eax,XREGS_fs+4(%esp)
+        movl %eax,XREGS_gs+4(%esp)
+nvm86_3:/* Rewrite our stack frame and return to ring 1. */
         /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
         andl $0xfffcbeff,XREGS_eflags+4(%esp)
         movl %gs,XREGS_ss+4(%esp)
@@ -297,19 +326,11 @@ FIX7:   sti
 DBLFLT2:jmp   process_guest_exception_and_events
 .previous
 .section __pre_ex_table,"a"
-       .long FLT7,FIX7
-       .long FLT8,FIX7
-       .long FLT9,FIX7
-       .long FLT10,FIX7
-       .long FLT11,FIX7
-       .long FLT12,FIX7
-       .long FLT13,FIX7
-       .long FLT14,FIX7
-       .long FLT15,FIX7
-       .long FLT16,FIX7
-       .long FLT17,FIX7
-       .long FLT18,FIX7
-       .long FLT19,FIX7
+       .long  FLT7,FIX7 ,  FLT8,FIX7 ,  FLT9,FIX7 , FLT10,FIX7
+       .long FLT11,FIX7 , FLT12,FIX7 , FLT13,FIX7 , FLT14,FIX7
+       .long FLT15,FIX7 , FLT16,FIX7 , FLT17,FIX7 , FLT18,FIX7
+       .long FLT19,FIX7 , FLT20,FIX7 , FLT21,FIX7 , FLT22,FIX7
+       .long FLT23,FIX7 , FLT24,FIX7 , FLT25,FIX7 , FLT26,FIX7 , FLT27,FIX7
 .previous
 .section __ex_table,"a"
         .long DBLFLT2,domain_crash
@@ -325,11 +346,12 @@ process_guest_exception_and_events:
 
         ALIGN
 ENTRY(ret_from_intr)
-       GET_CURRENT(%ebx)
-        movb XREGS_cs(%esp),%al
-       testb $3,%al    # return to non-supervisor?
-       jnz test_all_events
-       jmp restore_all_xen
+        GET_CURRENT(%ebx)
+        movl  XREGS_eflags(%esp),%eax
+        movb  XREGS_cs(%esp),%al
+        testl $(3|X86_EFLAGS_VM),%eax
+        jnz   test_all_events
+        jmp   restore_all_xen
 
 ENTRY(divide_error)
        pushl $TRAP_divide_error<<16
@@ -347,15 +369,18 @@ error_code:
        GET_CURRENT(%ebx)
        call  *SYMBOL_NAME(exception_table)(,%eax,4)
         addl  $4,%esp
+        movl  XREGS_eflags(%esp),%eax
         movb  XREGS_cs(%esp),%al
-       testb $3,%al
+        testl $(3|X86_EFLAGS_VM),%eax
        jz    restore_all_xen
         jmp   process_guest_exception_and_events
 
 exception_with_ints_disabled:
+        movl  XREGS_eflags(%esp),%eax
         movb  XREGS_cs(%esp),%al
-       testb $3,%al   # interrupts disabled outside Xen?
-       jnz   1b       # it really does happen! (e.g., DOM0 X server)
+        testl $(3|X86_EFLAGS_VM),%eax   # interrupts disabled outside Xen?
+        jnz   1b                        # it really does happen!
+                                        #  (e.g., DOM0 X server)
         pushl XREGS_eip(%esp)
         call  search_pre_exception_table
         addl  $4,%esp
@@ -469,8 +494,9 @@ ENTRY(nmi)
         # In all other cases we bail without touching DS-GS, as we have
         # interrupted an enclosing Xen activation in tricky prologue or
         # epilogue code.
+        movl  XREGS_eflags(%esp),%eax
         movb  XREGS_cs(%esp),%al
-       testb $3,%al
+        testl $(3|X86_EFLAGS_VM),%eax
         jnz   do_watchdog_tick
         movl  XREGS_ds(%esp),%eax
         cmpw  $(__HYPERVISOR_DS),%ax
@@ -494,8 +520,9 @@ do_watchdog_tick:
        pushl %edx   # regs
         call  SYMBOL_NAME(do_nmi)
        addl  $8,%esp
+        movl  XREGS_eflags(%esp),%eax
         movb  XREGS_cs(%esp),%al
-       testb $3,%al
+        testl $(3|X86_EFLAGS_VM),%eax
        jz    restore_all_xen
         GET_CURRENT(%ebx)
         jmp   restore_all_guest
@@ -539,7 +566,62 @@ nmi_io_err:
         call SYMBOL_NAME(io_check_error)                        
         addl $4,%esp
         jmp  ret_from_intr
-             
+
+
+ENTRY(setup_vm86_frame)
+        # Copies the entire stack frame forwards by 16 bytes.
+        .macro copy_vm86_words count=18
+        .if \count
+        pushl ((\count-1)*4)(%esp)
+        popl  ((\count-1)*4)+16(%esp)
+        copy_vm86_words "(\count-1)"
+        .endif
+        .endm
+        copy_vm86_words
+        addl $16,%esp
+        ret
+
+do_switch_vm86:
+        # Discard the return address
+        addl $4,%esp
+
+        movl XREGS_eflags(%esp),%ecx
+                
+        # GS:ESI == Ring-1 stack activation
+        movl XREGS_esp(%esp),%esi
+VFLT1:  movl XREGS_ss(%esp),%gs
+
+        # ES:EDI == Ring-0 stack activation
+        leal XREGS_eip(%esp),%edi
+
+        # Restore the hypercall-number-clobbered EAX on our stack frame
+VFLT2:  movl %gs:(%esi),%eax
+        movl %eax,XREGS_eax(%esp)
+        addl $4,%esi
+               
+       # Copy the VM86 activation from the ring-1 stack to the ring-0 stack
+        movl $(XREGS_user_sizeof-XREGS_eip)/4,%ecx
+VFLT3:  movl %gs:(%esi),%eax
+        stosl
+        addl $4,%esi
+        loop VFLT3
+
+        # Fix up EFLAGS
+        andl $~X86_EFLAGS_IOPL,XREGS_eflags(%esp)
+        andl $X86_EFLAGS_IOPL,%ecx # Ignore attempts to change EFLAGS.IOPL
+        jnz  1f
+        orl  $X86_EFLAGS_IF,%ecx   # EFLAGS.IOPL=0 => no messing with EFLAGS.IF
+1:      orl  $X86_EFLAGS_VM,%ecx   # Force EFLAGS.VM
+        orl  %ecx,XREGS_eflags(%esp)
+        
+        jmp test_all_events
+
+.section __ex_table,"a"
+        .long VFLT1,domain_crash
+        .long VFLT2,domain_crash
+        .long VFLT3,domain_crash
+.previous
+
 .data
 
 ENTRY(exception_table)
@@ -588,6 +670,7 @@ ENTRY(hypercall_table)
         .long SYMBOL_NAME(do_grant_table_op)     /* 20 */
         .long SYMBOL_NAME(do_vm_assist)
         .long SYMBOL_NAME(do_update_va_mapping_otherdomain)
+        .long SYMBOL_NAME(do_switch_vm86)
         .rept NR_hypercalls-((.-hypercall_table)/4)
         .long SYMBOL_NAME(do_ni_hypercall)
         .endr
index a102508c83048d380f98dda22a1e4fa840ef2a48..f08da34cf8767736c863f0ebcadeba5e72a4e0b8 100644 (file)
@@ -304,7 +304,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
     unsigned int  *pseg = NULL; /* segment for memory operand (NULL=default) */
 
     /* WARNING: We only work for ring-3 segments. */
-    if ( unlikely((regs->cs & 3) != 3) )
+    if ( unlikely(VM86_MODE(regs)) || unlikely(!RING_3(regs)) )
     {
         DPRINTK("Taken fault at bad CS %04x\n", regs->cs);
         goto fail;
index 1d377c506076f81bd10c5cdcbe11b4a6df46ed22..d44b2d5e620d75f4cd23f56218a61c5a38cd3843 100644 (file)
@@ -55,7 +55,8 @@ static inline int debugger_trap_entry(
         break;
 
     case TRAP_gp_fault:        
-        if ( ((regs->cs & 3) != 0) && ((regs->error_code & 3) == 2) &&
+        if ( (VM86_MODE(regs) || !RING_0(regs)) &&
+             ((regs->error_code & 3) == 2) &&
              pdb_initialized && (pdb_ctx.system_call != 0) )
         {
             unsigned long cr3 = read_cr3();
index 01244c8e90c8425860dcccce52376fa1a715e315..8231bb2dec0974abba974a9fc47425f6226e56ca 100644 (file)
@@ -11,7 +11,7 @@
 /* Maybe auto-generate the following two cases (quoted vs. unquoted). */
 #ifndef __ASSEMBLY__
 
-#define __SAVE_ALL_PRE(_reg) \
+#define __SAVE_ALL_PRE \
         "cld;" \
         "pushl %eax;" \
         "pushl %ebp;" \
         "pushl %edx;" \
         "pushl %ecx;" \
         "pushl %ebx;" \
-        "movb "STR(XREGS_cs)"(%esp),%"STR(_reg)"l;" \
-        "testb $3,%"STR(_reg)"l;" \
-        "je 1f;" \
+        "testl $"STR(X86_EFLAGS_VM)","STR(XREGS_eflags)"(%esp);" \
+        "jz 2f;" \
+        "call setup_vm86_frame;" \
+        "jmp 3f;" \
+        "2:testb $3,"STR(XREGS_cs)"(%esp);" \
+        "jz 1f;" \
         "movl %ds,"STR(XREGS_ds)"(%esp);" \
         "movl %es,"STR(XREGS_es)"(%esp);" \
         "movl %fs,"STR(XREGS_fs)"(%esp);" \
-        "movl %gs,"STR(XREGS_gs)"(%esp);"
+        "movl %gs,"STR(XREGS_gs)"(%esp);" \
+        "3:"
 
 #define SAVE_ALL_NOSEGREGS(_reg) \
-        __SAVE_ALL_PRE(_reg) \
+        __SAVE_ALL_PRE \
         "1:"
 
 #define SET_XEN_SEGMENTS(_reg) \
         "movl %e"STR(_reg)"x,%es;"
 
 #define SAVE_ALL(_reg) \
-        __SAVE_ALL_PRE(_reg) \
+        __SAVE_ALL_PRE \
         SET_XEN_SEGMENTS(_reg) \
         "1:"
 
 #else
 
-#define __SAVE_ALL_PRE(_reg) \
+#define __SAVE_ALL_PRE \
         cld; \
         pushl %eax; \
         pushl %ebp; \
         pushl %edx; \
         pushl %ecx; \
         pushl %ebx; \
-        movb XREGS_cs(%esp),% ## _reg ## l; \
-        testb $3,% ## _reg ## l; \
-        je 1f; \
+        testl $X86_EFLAGS_VM,XREGS_eflags(%esp); \
+        jz 2f; \
+        call setup_vm86_frame; \
+        jmp 3f; \
+        2:testb $3,XREGS_cs(%esp); \
+        jz 1f; \
         movl %ds,XREGS_ds(%esp); \
         movl %es,XREGS_es(%esp); \
         movl %fs,XREGS_fs(%esp); \
-        movl %gs,XREGS_gs(%esp);
+        movl %gs,XREGS_gs(%esp); \
+        3:
 
 #define SAVE_ALL_NOSEGREGS(_reg) \
-        __SAVE_ALL_PRE(_reg) \
+        __SAVE_ALL_PRE \
         1:
 
 #define SET_XEN_SEGMENTS(_reg) \
@@ -71,7 +79,7 @@
         movl %e ## _reg ## x,%es;
 
 #define SAVE_ALL(_reg) \
-        __SAVE_ALL_PRE(_reg) \
+        __SAVE_ALL_PRE \
         SET_XEN_SEGMENTS(_reg) \
         1:
 
index a4fdcc663a43e5b22011a01c5083d9c6e1b0a1d2..e03e2a8a4b55b28474e8534e32f423e265507a8c 100644 (file)
@@ -49,4 +49,10 @@ enum EFLAGS {
     EF_ID   = 0x00200000,   /* id */
 };
 
+#define VM86_MODE(_r) ((_r)->eflags & EF_VM)
+#define RING_0(_r)    (((_r)->cs & 3) == 0)
+#define RING_1(_r)    (((_r)->cs & 3) == 1)
+#define RING_2(_r)    (((_r)->cs & 3) == 2)
+#define RING_3(_r)    (((_r)->cs & 3) == 3)
+
 #endif
index f103509b041d351ce728382dd2e6a3f676d22757..905bd4c0119fd6b686f8a434007000b5df6674be 100644 (file)
@@ -48,6 +48,7 @@
 #define __HYPERVISOR_grant_table_op       20
 #define __HYPERVISOR_vm_assist            21
 #define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_switch_vm86          23
 
 /*
  * MULTICALLS